終於進到我們的主軸程式碼安全的部分啦~我這次是選擇C語言做為練習,就讓我們一起學習吧!
下方程式碼片段全部都是擷取自 Secure Code Warrior 線上安全程式培訓平台,因為練習互動時的題目多半不會只有單一個檔案,可能涉及多個檔案、資料夾及多處地方修改,因此我的文章主要是針對最主要的區塊做修改及說明,若有程式上不好理解的地方非常抱歉也還請見諒,也可以實際上去 Secure Code Warrior 玩玩看,搭配著互動,會更有感的學習哦~
形成原因:同一個記憶體位置上多次呼叫free()
函數
後果:使程式執行產生混亂,讓攻擊者能覆寫或執行任意程式碼
在哪出現:任何呼叫釋放的地方,free()
函數將之前calloc()
, malloc()
和realloc()
分配記憶體的地方解除分配
實例:
攻擊者發送了一個包含多個 free()
函數調用的 GIF 文件。當用戶點擊這個 GIF 時,會觸發漏洞。這個 GIF 使用一個名為 rasterbits
的緩衝區來儲存圖像數據,並且多個已編碼的影格(frame)共用這個緩衝區。
但是,當 rasterbits
符合以下三個條件之一時,該緩衝區會被釋放:
1. width * height
大於 originalWidth * originalHeight
2. width - originalWidth > 0
3. height - originalHeight > 0
如果重新分配(re-allocation)的大小設為 0,則會導致 re-allocation(0)
等同於 free()
,從而釋放記憶體。然而,攻擊者將重新分配的大小設置為 100, 0, 0,這樣的操作會導致系統錯誤地釋放同一塊記憶體兩次,從而觸發雙重釋放的漏洞,進一步可能被攻擊者利用來攻擊系統。
Database::~Database() {
delete this->db;
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:Database
類別指向SQLite::Database
類別物件的指標。此指標未在此類別中初始化,也不由建構函式填寫。刪除未初始化的指標是未定義的行為。
把此區塊刪除:
void Database::checkDatabase() {
db = new SQLite::Database(
/* DB path */ db_filename,
/* DB flags */ SQLite::OPEN_CREATE | SQLite::OPEN_READWRITE
);
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
及刪除此段程式碼:
delete this->db;
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
並在底下修正:
Database::Database(std::string& db_filename, User& user):
db_filename(db_filename),
user(user)
{
this->db = std::make_unique<SQLite::Database>(
/* DB path */ db_filename,
/* DB flags */ SQLite::OPEN_CREATE | SQLite::OPEN_READWRITE
);
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:Std::unique_ptr
自動管理指向已建立物件的指標。當該物件超出範圍時,它會自動刪除。